package com.sprouting.ops.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sprouting.ops.annotations.invoke.IdempotentSingle;
import com.sprouting.ops.interfaces.AddGroup;
import com.sprouting.ops.interfaces.ConstantBase;
import com.sprouting.ops.interfaces.UpdGroup;
import com.sprouting.ops.model.DromaraFileStorage;
import com.sprouting.ops.model.OpsApp;
import com.sprouting.ops.model.OpsAppBranch;
import com.sprouting.ops.model.ResultJson;
import com.sprouting.ops.model.bo.OpsAppBo;
import com.sprouting.ops.model.qo.OpsAppComputerServerQo;
import com.sprouting.ops.model.qo.OpsAppQo;
import com.sprouting.ops.model.qo.OpsComponentComputerServerQo;
import com.sprouting.ops.model.vo.OpsAppVo;
import com.sprouting.ops.service.DromaraFileStorageService;
import com.sprouting.ops.service.OpsAppService;
import com.sprouting.ops.service.OpsComponentService;
import com.sprouting.ops.utils.CheckTool;
import com.sprouting.ops.utils.EntityTool;
import com.sprouting.ops.utils.IdTool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * (应用项目表)表控制层
 *
 * @author longx
 * @since 2023-11-19 12:51:25
 */
@Slf4j
@RestController
@RequestMapping("opsApp")
public class OpsAppController {

    @Resource
    private OpsAppService opsAppService;
    @Resource
    private OpsComponentService opsComponentService;
    @Resource
    private DromaraFileStorageService dromaraFileStorageService;


    /**
     * 根据计算机id查询应用信息
     * @param query 查询参数
     * @return
     */
    @PostMapping("getAppByComputerId")
    public ResultJson getAppByComputerId(@Validated OpsAppComputerServerQo query){
        Page page = query.getPage();
        return ResultJson.success(opsAppService.getAppByComputerId(page, query));
    }

    /**
     * 根据计算机id查询组件信息
     * @param query 查询参数
     * @return
     */
    @PostMapping("getComponentByComputerId")
    public ResultJson getComponentByComputerId(@Validated OpsComponentComputerServerQo query){
        Page page = query.getPage();
        return ResultJson.success(opsComponentService.getComponentByComputerId(page, query));
    }

    /**
     * 根据产品id查询应用
     * @param productId 产品id
     * @return
     */
    @PostMapping("getAppByProductId")
    public ResultJson getAppByProductId(String productId){
        if (CheckTool.checkNull(productId)){
            return ResultJson.errorCheck();
        }
        List<OpsAppVo> appList = opsAppService.getAppByProductId(productId);
        return ResultJson.success(appList);
    }

    /**
     * 逻辑删除
     * @param opsAppId 主键
     * @return
     */
    @IdempotentSingle
    @PostMapping("delOpsApp")
    public ResultJson delOpsApp(String opsAppId){
        if (CheckTool.checkNull(opsAppId)){
            return ResultJson.errorCheck();
        }

        OpsApp opsApp = opsAppService.getById(opsAppId);
        if (opsApp == null){
            return ResultJson.success();
        }

        DromaraFileStorage opsUploadFile = dromaraFileStorageService.delFileBefore(opsApp.getIco());

        List<DromaraFileStorage> bindList = dromaraFileStorageService.getByBindId(opsAppId);

        // 逻辑删除
        opsAppService.delOpsApp(opsApp, opsUploadFile, bindList);
        return ResultJson.success();
    }

    /**
     * 分页查询
     * @param query 查询参数
     * @return
     */
    @RequestMapping("getOpsAppPageList")
    public ResultJson getOpsAppPageList(@Validated OpsAppQo query){
        Page page = query.getPage();
        Page<OpsAppVo> opsAppPageList = opsAppService.getOpsAppPageList(page, query);
        if (CollUtil.isEmpty(opsAppPageList.getRecords())){
            return ResultJson.success(opsAppPageList);
        }

        for (OpsAppVo record : opsAppPageList.getRecords()) {
            if (StrUtil.isEmpty(record.getOs())){
                continue;
            }

            // 转换 os 为集合
            List<Integer> list = Arrays.stream(record.getOs().split(",")).map(Integer::parseInt).collect(Collectors.toList());
            record.setOsList(list);
            record.setOsStr(getOs(list));
        }
        return ResultJson.success(opsAppPageList);
    }

    /**
     * 保存
     * @param opsAppBo 保存对象
     * @return
     */
    @IdempotentSingle
    @PostMapping("saveOpsApp")
    public ResultJson saveOpsApp(@Validated(AddGroup.class) OpsAppBo opsAppBo){
        String msg = checkOpsApp(opsAppBo);
        if (msg != null){
            return ResultJson.error(msg);
        }

        OpsApp opsApp = BeanUtil.copyProperties(opsAppBo, OpsApp.class);

        opsApp.setId(IdTool.getId());
        EntityTool.saveBase(opsApp);

        // 创建同时增加一个主分支
        OpsAppBranch branch = new OpsAppBranch();
        branch.setId(IdTool.getId());
        branch.setAppId(opsApp.getId());
        branch.setBranchName("master");
        branch.setIntroduce("项目主分支");
        branch.setStatus(ConstantBase.MaintenanceStatus.CONTINUOUS);
        EntityTool.saveBase(branch);

        // 处理文件
        DromaraFileStorage unifiedFileInfo = dromaraFileStorageService.toProductionBefore(opsAppBo.getIco(), opsAppBo.getId(), ConstantBase.FileSourceType.APP);

        // 提取Markdown的数据
        List<DromaraFileStorage> installList = dromaraFileStorageService.getMarkdownImagesUrlToFileStorage(opsAppBo.getInstallDoc(), opsAppBo.getId(), ConstantBase.FileSourceType.APP_INSTALL_DOC);


        opsAppService.saveOpsApp(opsApp, unifiedFileInfo, installList, branch);
        return ResultJson.success(opsApp);
    }

    /**
     * 更新
     * @param opsAppBo 更新对象
     * @return
     */
    @IdempotentSingle
    @PostMapping("updOpsApp")
    public ResultJson updOpsApp(@Validated(UpdGroup.class) OpsAppBo opsAppBo){
        String msg = checkOpsApp(opsAppBo);
        if (msg != null){
            return ResultJson.error(msg);
        }

        OpsApp opsApp = BeanUtil.copyProperties(opsAppBo, OpsApp.class);

        // 不能修改文件
        OpsApp oldDb = opsAppService.getById(opsAppBo.getId());
        DromaraFileStorage[] uploadFileArray = dromaraFileStorageService.updFileBefore(opsAppBo.getIco(), oldDb.getIco(), opsAppBo.getId(), ConstantBase.FileSourceType.APP);

        // 提取Markdown的数据
        // 修改的时候也要提取，然后转换为生产的数据，这里要注意的是，修改的时候，不考虑去删除旧的数据的问题，到时候删除的时候，直接使用objId统一处理即可，因为这个数据量还是比较小的，没必要找的旧的去删，新的去加，搞麻烦了
        List<DromaraFileStorage> installList = dromaraFileStorageService.getMarkdownImagesUrlToFileStorage(opsAppBo.getInstallDoc(), opsAppBo.getId(), ConstantBase.FileSourceType.APP_INSTALL_DOC);

        EntityTool.updBase(opsApp);
        opsAppService.updOpsApp(opsApp, uploadFileArray, installList);
        return ResultJson.success(opsApp);
    }

    /**
     * 检查
     * @param opsAppBo 校验对象
     * @return 非null则有异常
     */
    private String checkOpsApp(OpsAppBo opsAppBo){
        OpsApp dbName = opsAppService.getByNameFilterId(opsAppBo.getName(), opsAppBo.getId());
        if (dbName != null){
            return "项目下已存在同名的应用";
        }

        // 补充数据
        if (CollUtil.isEmpty(opsAppBo.getOsList())){
            List<Integer> osList = new ArrayList<>();
            osList.add(ConstantBase.OsType.LINUX);
            osList.add(ConstantBase.OsType.WINDOWS);
            osList.add(ConstantBase.OsType.MAC);
            osList.add(ConstantBase.OsType.UNIX);
            // osList.add(ConstantBase.OsType.YHQL);
            // osList.add(ConstantBase.OsType.TXUOS);
            // osList.add(ConstantBase.OsType.SD);
            // osList.add(ConstantBase.OsType.OULA);
            // osList.add(ConstantBase.OsType.ZXXZD);
            // osList.add(ConstantBase.OsType.HQ);
            // osList.add(ConstantBase.OsType.HARMONY);
            // osList.add(ConstantBase.OsType.ZBQL);
            opsAppBo.setOs(StrUtil.join(",", osList));

        } else {
            opsAppBo.setOs(StrUtil.join(",", opsAppBo.getOsList()));
        }
        if (opsAppBo.getSort() == null){
            opsAppBo.setSort(ConstantBase.DefaultValue.SORT);
        }
        if (opsAppBo.getCommon() == null){
            opsAppBo.setCommon(ConstantBase.YesOrNo.NO);
        }
        if (opsAppBo.getState() == null){
            opsAppBo.setState(ConstantBase.AppState.DEV);
        }
        if (opsAppBo.getType() == null){
            opsAppBo.setType(ConstantBase.AppType.JAVA);
        }
        if (CheckTool.checkNull(opsAppBo.getLanguage())){
            opsAppBo.setLanguage("java");
        }
        if (opsAppBo.getImportance() == null){
            opsAppBo.setImportance(ConstantBase.Importance.ORDINARY);
        }
        if (opsAppBo.getMicroservices() == null){
            opsAppBo.setMicroservices(ConstantBase.YesOrNo.NO);
        }
        if (opsAppBo.getDistributed() == null){
            opsAppBo.setDistributed(ConstantBase.YesOrNo.NO);
        }

        return null;
    }

    /**
     * 获取转中文后的系统类型
     * @param list 选中的类型
     * @return
     */
    private String getOs(List<Integer> list){
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < list.size(); i ++){
            Integer i1 = list.get(i);
            sb.append(ConstantBase.OsType.MAP.get(i1));
            if (i != list.size() - 1){
                sb.append(",");
            }
        }

        return sb.toString();
    }
}

